{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyO89L7nv9/pdmZVzUVpKS+b",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/sugarforever/LangChain-Advanced/blob/main/Retrievers/01_MultiQuery_Retriever.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xPWZLTgY5E_4",
        "outputId": "4e54d9d6-64dd-4aa6-d025-2af049efc249"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[?25l     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/1.8 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K     \u001b[91m━━━━━━━\u001b[0m\u001b[90m╺\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.3/1.8 MB\u001b[0m \u001b[31m9.6 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.8/1.8 MB\u001b[0m \u001b[31m25.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.0/77.0 kB\u001b[0m \u001b[31m8.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m437.8/437.8 kB\u001b[0m \u001b[31m32.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m66.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m65.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m66.3/66.3 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m59.5/59.5 kB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.4/5.4 MB\u001b[0m \u001b[31m64.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.2/6.2 MB\u001b[0m \u001b[31m64.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.8/3.8 MB\u001b[0m \u001b[31m65.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m593.7/593.7 kB\u001b[0m \u001b[31m43.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.4/49.4 kB\u001b[0m \u001b[31m4.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.0/67.0 kB\u001b[0m \u001b[31m6.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m268.8/268.8 kB\u001b[0m \u001b[31m23.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m428.8/428.8 kB\u001b[0m \u001b[31m39.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.1/4.1 MB\u001b[0m \u001b[31m87.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.3/1.3 MB\u001b[0m \u001b[31m46.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m129.9/129.9 kB\u001b[0m \u001b[31m12.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m7.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n"
          ]
        }
      ],
      "source": [
        "!pip install -q -U langchain openai chromadb tiktoken"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import os\n",
        "os.environ['OPENAI_API_KEY'] = \"your valid openai api key\""
      ],
      "metadata": {
        "id": "eVQjKJn-5ZZZ"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "import logging\n",
        "\n",
        "logging.basicConfig()\n",
        "logging.getLogger(\"langchain.retrievers.multi_query\").setLevel(logging.INFO)"
      ],
      "metadata": {
        "id": "hLkz1l-25xLY"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.vectorstores import Chroma\n",
        "from langchain.document_loaders import WebBaseLoader\n",
        "from langchain.embeddings.openai import OpenAIEmbeddings\n",
        "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
        "\n",
        "# Load blog post\n",
        "loader = WebBaseLoader(\"https://blog.langchain.dev/langchain-prompt-hub/\")\n",
        "data = loader.load()\n",
        "\n",
        "# Split\n",
        "text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)\n",
        "splits = text_splitter.split_documents(data)\n",
        "\n",
        "# VectorDB\n",
        "embedding = OpenAIEmbeddings()\n",
        "vectordb = Chroma.from_documents(documents=splits, embedding=embedding)"
      ],
      "metadata": {
        "id": "wXOpXACj5YKS"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain.chat_models import ChatOpenAI\n",
        "from langchain.retrievers.multi_query import MultiQueryRetriever\n",
        "\n",
        "question = \"What can we do with LangChain hub?\"\n",
        "llm = ChatOpenAI(temperature=0)\n",
        "retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectordb.as_retriever(), llm=llm)"
      ],
      "metadata": {
        "id": "G1dVQCZA5mMt"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "unique_docs = retriever_from_llm.get_relevant_documents(query=question)\n",
        "unique_docs"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wJUcf3kW52es",
        "outputId": "682eccc9-8852-406e-f7db-59eee22e24ec"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "INFO:langchain.retrievers.multi_query:Generated queries: ['1. How can the LangChain hub be utilized?', '2. What are the possible applications of the LangChain hub?', '3. In what ways can the LangChain hub be used effectively?']\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[Document(page_content=\"Today, we're excited to launch LangChain Hub‚Äìa home for uploading, browsing, pulling, and managing your prompts. (Soon, we'll be adding other artifacts like chains and agents).\\uf8ffüí°Explore the Hub hereLangChain Hub is built into LangSmith (more on that below) so there are 2 ways to start exploring LangChain Hub.With LangSmith access: Full read and write permissions. You can explore all existing prompts and upload your own by logging in and navigate to the Hub from your admin panel.Without\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"way to facilitate this kind of collaboration.We're aiming to make LangChain Hub the best place for teams to write and manage prompts, together. The product isn't quite there today‚Äìthis first iteration only supports personal accounts‚Äìbut we're actively looking for organizations that are excited to explore an Alpha with us so if you want organizational support for the Hub, please reach out to us directly at support@langchain.dev with the subject [Hub: Orgs]4. Artifact Management and\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"applications. It's about advancing our collective wisdom and translating that into knowledge we can all put to use now. We want to help make this easier on an individual, team, and organization scale, across any use-case and every industry. Our goal for LangChain Hub is that it becomes the go-to place for developers to discover new use cases and polished prompts.Today, polished prompts and the wisdom that comes with it are distributed across the web and all-too-often buried in the crannies of\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content='Announcing LangChain Hub\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n                            LangChain\\n                    \\n\\n\\n\\n\\n\\n\\nHome\\nBy LangChain\\nRelease Notes\\nGitHub\\nDocs\\nWrite with Us\\n\\n\\n\\n\\n\\nSign in\\nSubscribe\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n                        Sep 5, 2023\\n                    \\n\\n\\n                        6 min read\\n                    \\n\\n\\n                            By LangChain\\n                        \\n\\n\\nAnnouncing LangChain Hub', metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"syntax (e.g. SYS and INST for Llama2).As developers explore the wide variety of models, we hope the LangChain Hub can assist in that exploration by providing starter prompts for those models. We've added tags to prompts to indicate which model(s) they work best with.2. InspectabilityPrompts power the chains and agents in LangChain. Often times, the prompts are obfuscated away. We built LangChain Hub in a way that puts them front and center, so that anyone can see what's going on under the\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"LangSmithFrom partnering with early LangSmith users, the tie-in between debugging, logging, testing, and evaluation and artifact management has become increasingly obvious. By making LangChain Hub a part of LangSmith, we knew we could help teams not only identify and collaborate on prompts, but also make informed decisions about how to implement them. Testing integrations with prompts aren't out yet but they are coming soon!Favorite FeaturesHome PageWe want to make discoverability and\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'})]"
            ]
          },
          "metadata": {},
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from typing import List\n",
        "from langchain.chains import LLMChain\n",
        "from pydantic import BaseModel, Field\n",
        "from langchain.prompts import PromptTemplate\n",
        "from langchain.output_parsers import PydanticOutputParser\n",
        "from langchain.retrievers.multi_query import LineListOutputParser\n",
        "\n",
        "\n",
        "# Output parser will split the LLM result into a list of queries\n",
        "'''\n",
        "class LineList(BaseModel):\n",
        "    # \"lines\" is the key (attribute name) of the parsed output\n",
        "    lines: List[str] = Field(description=\"Lines of text\")\n",
        "\n",
        "\n",
        "class LineListOutputParser(PydanticOutputParser):\n",
        "    def __init__(self) -> None:\n",
        "        super().__init__(pydantic_object=LineList)\n",
        "\n",
        "    def parse(self, text: str) -> LineList:\n",
        "        print(f\"Input text: {text}\")\n",
        "        lines = text.strip().split(\"\\n\")\n",
        "        return LineList(lines=lines)\n",
        "'''\n",
        "\n",
        "output_parser = LineListOutputParser()\n",
        "\n",
        "QUERY_PROMPT = PromptTemplate(\n",
        "    input_variables=[\"question\"],\n",
        "    template=\"\"\"You are an AI language model assistant. Your task is to generate five\n",
        "    different versions of the given user question to retrieve relevant documents from a vector\n",
        "    database. By generating multiple perspectives on the user question, your goal is to help\n",
        "    the user overcome some of the limitations of the distance-based similarity search.\n",
        "    Provide these alternative questions seperated by newlines.\n",
        "    Original question: {question}\"\"\",\n",
        ")\n",
        "llm = ChatOpenAI(temperature=0)\n",
        "\n",
        "# Chain\n",
        "llm_chain = LLMChain(llm=llm, prompt=QUERY_PROMPT, output_parser=output_parser)"
      ],
      "metadata": {
        "id": "qbqSmDne57Qj"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Run\n",
        "retriever = MultiQueryRetriever(\n",
        "    retriever=vectordb.as_retriever(), llm_chain=llm_chain, parser_key=\"lines\"\n",
        ")  # \"lines\" is the key (attribute name) of the parsed output\n",
        "\n",
        "unique_docs = retriever.get_relevant_documents(query=question)\n",
        "unique_docs"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "b1Art5pt6I3k",
        "outputId": "8bb4db8a-36c2-4bf1-f05f-698358281336"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "INFO:langchain.retrievers.multi_query:Generated queries: ['1. How can the LangChain hub be utilized?', '2. What are the possible applications of the LangChain hub?', '3. In what ways can the LangChain hub be used?', '4. What functionalities does the LangChain hub offer?', '5. What are the potential uses of the LangChain hub?']\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[Document(page_content=\"Today, we're excited to launch LangChain Hub‚Äìa home for uploading, browsing, pulling, and managing your prompts. (Soon, we'll be adding other artifacts like chains and agents).\\uf8ffüí°Explore the Hub hereLangChain Hub is built into LangSmith (more on that below) so there are 2 ways to start exploring LangChain Hub.With LangSmith access: Full read and write permissions. You can explore all existing prompts and upload your own by logging in and navigate to the Hub from your admin panel.Without\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"way to facilitate this kind of collaboration.We're aiming to make LangChain Hub the best place for teams to write and manage prompts, together. The product isn't quite there today‚Äìthis first iteration only supports personal accounts‚Äìbut we're actively looking for organizations that are excited to explore an Alpha with us so if you want organizational support for the Hub, please reach out to us directly at support@langchain.dev with the subject [Hub: Orgs]4. Artifact Management and\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"applications. It's about advancing our collective wisdom and translating that into knowledge we can all put to use now. We want to help make this easier on an individual, team, and organization scale, across any use-case and every industry. Our goal for LangChain Hub is that it becomes the go-to place for developers to discover new use cases and polished prompts.Today, polished prompts and the wisdom that comes with it are distributed across the web and all-too-often buried in the crannies of\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content='Announcing LangChain Hub\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n                            LangChain\\n                    \\n\\n\\n\\n\\n\\n\\nHome\\nBy LangChain\\nRelease Notes\\nGitHub\\nDocs\\nWrite with Us\\n\\n\\n\\n\\n\\nSign in\\nSubscribe\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n                        Sep 5, 2023\\n                    \\n\\n\\n                        6 min read\\n                    \\n\\n\\n                            By LangChain\\n                        \\n\\n\\nAnnouncing LangChain Hub', metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"syntax (e.g. SYS and INST for Llama2).As developers explore the wide variety of models, we hope the LangChain Hub can assist in that exploration by providing starter prompts for those models. We've added tags to prompts to indicate which model(s) they work best with.2. InspectabilityPrompts power the chains and agents in LangChain. Often times, the prompts are obfuscated away. We built LangChain Hub in a way that puts them front and center, so that anyone can see what's going on under the\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'}),\n",
              " Document(page_content=\"LangSmithFrom partnering with early LangSmith users, the tie-in between debugging, logging, testing, and evaluation and artifact management has become increasingly obvious. By making LangChain Hub a part of LangSmith, we knew we could help teams not only identify and collaborate on prompts, but also make informed decisions about how to implement them. Testing integrations with prompts aren't out yet but they are coming soon!Favorite FeaturesHome PageWe want to make discoverability and\", metadata={'language': 'en', 'source': 'https://blog.langchain.dev/langchain-prompt-hub/', 'title': 'Announcing LangChain Hub'})]"
            ]
          },
          "metadata": {},
          "execution_count": 9
        }
      ]
    }
  ]
}